<?php
declare(strict_types=1);

namespace app\common\business;

use app\common\lib\Arr;
use app\common\lib\Key;
use think\Exception;
use think\facade\Cache;

class Cart extends BusiBase
{
    /**
     * 获取购物车商品件数
     *
     * @param int $userId
     * @return int
     */
    public function getCartCount(int $userId)
    {
        try {
            $count = Cache::hLen(Key::userCart($userId));
        } catch (\Exception $e) {
            $this->errorLog('get cart count error: '.$e->getMessage());
            return 0;
        }
        return intval($count);
    }

    /**
     * 添加商品到购物车
     *
     * @param int $userId
     * @param int $skuId
     * @param int $number
     * @return false
     */
    public function addRedis(int $userId, int $skuId, int $number)
    {
        $goodsSku = new GoodsSku();
        $goods    = $goodsSku->getNormalSkuAndGoods($skuId);
        if (!$goodsSku) return FALSE;
        $data     = [
            'goods_id' => $goods['goods']['id'],
            'title'    => $goods['goods']['title'],
            'image'    => $goods['goods']['recommend_image'],
            'num'      => $number,
            'create_time' => time()
        ];

        try {
            $has = Cache::hGet(Key::userCart($userId), $skuId);
            if ($has) {
                $hasData = json_decode($has, true);
                $data['num'] += $hasData['num'];
                // 判断库存是否充足
                if ($data['num'] > $goods['stock']) throw new Exception($data['title'].' 库存不足');
            }
            $res = Cache::hSet(Key::userCart($userId), $skuId, json_encode($data));
        } catch (\Exception $e) {
            $this->errorLog('cache redis data '.json_encode($data)." error: ".$e->getMessage());
            return　FALSE;
        }
        return $res;
    }

    /**
     * 删除购物车商品
     *
     * @param int $userId
     * @param int $skuId
     * @return false
     */
    public function deleteRdis(int $userId, $skuId)
    {
        if (!is_array($skuId)) {
            $skuId = explode(',', (string) $skuId);
        }
        try {
            $res = Cache::hDel(Key::userCart($userId), ...$skuId);
        } catch (\Exception $e) {
            $this->errorLog("delete redis userId:$userId skuId:$skuId error: ".$e->getMessage());
            return FALSE;
        }
        return $res;
    }

    /**
     * 修改购物车商品信息
     *
     * @param int $userId
     * @param int $skuId
     * @param int $number
     * @return false
     * @throws Exception
     */
    public function updateRedis(int $userId, int $skuId, int $number)
    {
        try {
            $has = Cache::hGet(Key::userCart($userId), $skuId);
        } catch (\Exception $e) {
            $this->errorLog("hget redis user:$userId id:$skuId error: ".$e->getMessage());
            return FALSE;
        }
        if (!$has) throw new Exception('您的购物车没有该商品，请先添加');
        // 获取当前商品 sku 数据
        $skuData = (new GoodsSku())->getById($skuId);
        $data = json_decode($has, true);
        // 判断当前商品库存是否充足
        if ($number > $skuData['stock']) throw new Exception('库存不足');
        $data['num'] = $number;
        try {
            $result = Cache::hSet(Key::userCart($userId), $skuId, json_encode($data));
        } catch (\Exception $e) {
            $this->errorLog("hset redis user:$userId id:$skuId num to $number error: ".$e->getMessage());
            return FALSE;
        }
        return $result;
    }

    /**
     * 购物车商品列表查询
     *
     * @param int $userId
     * @return array
     */
    public function lists(int $userId, string $idStr = null)
    {
        try {
            // 判断提交订单 ID 数组是否存在（存在时提取键名相交数据）
            if ($idStr) {
                $idArr = explode(',', $idStr);
                $cartData = Cache::hMget(Key::userCart($userId), $idArr);
                if (in_array('false', array_values($cartData))) return [];
            } else {
                $cartData = Cache::hGetAll(Key::userCart($userId));
            }
        } catch (\Exception $e) {
            $this->errorLog("get $userId redis cache error: ".$e->getMessage());
            return [];
        }
        if (!$cartData) return [];

        $result = [];
        // 获取商品信息
        $skuIdArr = array_keys($cartData);
        $skuGoods = (new GoodsSku())->getNormalByIdArr($skuIdArr);
        $skuIdPriceArr = array_column($skuGoods, 'price', 'id');
        $stockArr      = array_column($skuGoods, 'stock', 'id');
        $skuSpecsValueIdsArr = array_column($skuGoods, 'specs_value_ids', 'id');
        $sku = (new SpecsValue())->getCartSpecsValue($skuSpecsValueIdsArr);

        // 生成商品信息数组
        foreach ($cartData as $key=>$val) {
            $data = json_decode($val, true);
            if ($idStr && $stockArr[$key] && $stockArr[$key] < $data['num']) {
                throw new Exception("{$data['title']} 商品库存不足");
            }
            $data['id'] = $key;
            $data['image'] = preg_match('/^http/', $data['image']) ? $data['image'] : request()->domain().$data['image'];
            $data['price'] = $skuIdPriceArr[$key] ?? 0;
            $data['total_price'] = $data['price'] * $data['num'];
            $data['sku'] = $sku[$key] ?? "暂无规格";
            // 结果按时间进行降序排序
            $result[] = $data;
        }
        $result = Arr::arraySortByKey($result, 'create_time');
        return $result;
    }
}